package cn.net.yugu.doraemon.redis;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.springframework.data.redis.core.*;
import org.springframework.lang.Nullable;

import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @description:
 * @author: wanghongli
 * @create: 2022-07-18 00:05:43
 */
@SuppressWarnings("unchecked")
public final class RedisUtils {
    private static RedisTemplate<String, String> template;

    public static void setTemplate(RedisTemplate<String, String> template) {
        RedisUtils.template = template;
    }

    public static RedisTemplate<String, String> getTemplate() {
        return template;
    }

    public static Boolean setIfAbsent(String key, String value, Duration duration) {
        return template.opsForValue().setIfAbsent(key, value, duration);
    }

    public static <T> T getObject(String key, Class<T> clazz) {
        String valStr = RedisUtils.get(key);
        if (valStr == null || valStr.length() == 0) {
            return null;
        }
        if (clazz.isAssignableFrom(String.class)) {
            return (T) valStr;
        }
        return JSON.parseObject(valStr, clazz);
    }

    public static <T> T getObject(String key, TypeReference<T> typeReference) {
        String valStr = RedisUtils.get(key);
        if (valStr == null || valStr.length() == 0) {
            return null;
        }
        return JSON.parseObject(valStr, typeReference);
    }

    public static void setObject(String key, Object val, long ttl) {
        String valStr;
        if (val == null) {
            valStr = "";
        } else if (val.getClass().isAssignableFrom(String.class)) {
            valStr = (String) val;
        } else {
            valStr = JSON.toJSONString(val);
        }
        RedisUtils.set(key, valStr, ttl);
    }

    public static void expire(String key) {
        template.expire(key, 0, TimeUnit.SECONDS);
    }

    public static void expire(String key, long timeoutSeconds) {
        template.expire(key, timeoutSeconds, TimeUnit.SECONDS);
    }

    public static void expireAt(String key, Date date) {
        template.expireAt(key, date);
    }

    public static Long getExpireMillis(String key) {
        return template.getExpire(key, TimeUnit.MILLISECONDS);
    }

    public static void delete(String key) {
        template.delete(key);
    }

    public static void delete(Collection<String> keys) {
        template.delete(keys);
    }

    public static void set(String key, String value) {
        template.opsForValue().set(key, value);
    }

    public static void set(String key, String value, long timeout) {
        template.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }

    public static String get(String key) {
        return template.opsForValue().get(key);
    }

    public static void multiSet(Map<String, String> map) {
        template.opsForValue().multiSet(map);
    }

    @Nullable
    public static String getAndSet(String key, String value) {
        return template.opsForValue().getAndSet(key, value);
    }

    @Nullable
    public static List<String> multiGet(Collection<String> keys) {
        return template.opsForValue().multiGet(keys);
    }

    @Nullable
    public static Long increment(String key) {
        return template.opsForValue().increment(key);
    }

    @Nullable
    public static Long increment(String key, long delta) {
        return template.opsForValue().increment(key, delta);
    }

    @Nullable
    public static Double increment(String key, double delta) {
        return template.opsForValue().increment(key, delta);
    }

    @Nullable
    public static Long decrement(String key) {
        return template.opsForValue().decrement(key);
    }

    @Nullable
    public static Long decrement(String key, long delta) {
        return template.opsForValue().decrement(key, delta);
    }

    @Nullable
    public static Long sadd(String key, String... values) {
        return template.opsForSet().add(key, values);
    }

    @Nullable
    public static Long sremove(String key, String... values) {
        return template.opsForSet().remove(key, values);
    }

    @Nullable
    public static String spop(String key) {
        return template.opsForSet().pop(key);
    }

    @Nullable
    public static List<String> spop(String key, long count) {
        return template.opsForSet().pop(key, count);
    }

    @Nullable
    public static Long ssize(String key) {
        return template.opsForSet().size(key);
    }

    @Nullable
    public static Boolean sisMember(String key, String o) {
        return template.opsForSet().isMember(key, o);
    }

    @Nullable
    public static Map<Object, Boolean> sisMember(String key, String... objects) {
        return template.opsForSet().isMember(key, objects);
    }

    @Nullable
    public static Set<String> smembers(String key) {
        return template.opsForSet().members(key);
    }

    public static Cursor<String> sscan(String key, ScanOptions options) {
        return template.opsForSet().scan(key, options);
    }

    public static Long hdelete(String key, String... hashKeys) {
        return template.opsForHash().delete(key, hashKeys);
    }

    public static Boolean hhasKey(String key, String hashKey) {
        return template.opsForHash().hasKey(key, hashKey);
    }

    @Nullable
    public static String hget(String key, Object hashKey) {
        return (String) template.opsForHash().get(key, hashKey);
    }

    public static List<Object> hmultiGet(String key, Collection<Object> hashKeys) {
        return template.opsForHash().multiGet(key, hashKeys);
    }

    public static Long hincrement(String key,String hashKey, long delta) {
        return template.opsForHash().increment(key, hashKey, delta);
    }

    public static Double hincrement(String key, String hashKey, double delta) {
        return template.opsForHash().increment(key, hashKey, delta);
    }

    public static Set<Object> hkeys(String key) {
        return template.opsForHash().keys(key);
    }

    public static Long hsize(String key) {
        return template.opsForHash().size(key);
    }

    public static void hputAll(String key, Map<String, String> m) {
        template.opsForHash().putAll(key, m);
    }

    public static void hput(String key, String hashKey, String value) {
        template.opsForHash().put(key, hashKey, value);
    }

    public static List<Object> hvalues(String key) {
        return template.opsForHash().values(key);
    }

    public static Cursor<Map.Entry<Object, Object>> hscan(String key, ScanOptions options) {
        return template.opsForHash().scan(key, options);
    }
}
